package entidades;

import util.Util;
import util.MySQL;
import java.util.Map;
import java.util.Date;
import java.util.List;
import java.util.HashMap;
import java.util.LinkedList;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.google.gson.Gson;

/**
 *
 * @author JFM
 */
public class EtapaNewlong extends Entidad
	{
	private int orden;
	private int cicloId;
	private int formatoId;
	private long cantidad;
	private long ocupado;
	
	private Formato formato;
	private CicloNewlong ciclo;

	static final String NOMBRE_TABLA = "etapas_newlong";



	// --- Constructores --- //

	public EtapaNewlong()
		{
		id = 0;
		orden = 0;
		cantidad = 0;
		ocupado = 0;

		formatoId = 0;
		formato = null;
		cicloId = 0;
		ciclo = null;
		}

	public EtapaNewlong(int id) throws SQLException
		{ super(id); }

	public EtapaNewlong(String id) throws SQLException
		{ super(id); }

	public EtapaNewlong(ResultSet result) throws SQLException
		{ super(result); }



	// --- Metodos get()/set() --- //

	public int getOrden()
		{ return orden; }
	public void setOrden(int orden)
		{ this.orden = orden; }
	public void setOrden(String orden)
		{ try{ this.orden = Integer.parseInt(orden); }catch(Exception e) {}; }

	public long getCantidad()
		{ return cantidad; }
	public void setCantidad(long cantidad)
		{ this.cantidad = cantidad; }
	public void setCantidad(String cantidad)
		{ try{ this.cantidad = Integer.parseInt(cantidad); }catch(Exception e) {}; }

	public long getOcupado()
		{ return ocupado; }
	public void setOcupado(long ocupado)
		{ this.ocupado = ocupado; }
	public void setOcupado(String ocupado){
            try{
                this.ocupado = Integer.parseInt(ocupado);
            }catch(Exception e) {
                e.printStackTrace();
            }; 
        }

	public long getDisponible()
		{ return cantidad - ocupado; }
	
	public Date getFechaFin() throws SQLException
		{
		Date fechaFin = null;
		ResultSet result = MySQL.executeQuery("SELECT EtapasNewlong_Fechas('f', " + id + ") AS fecha_hora_fin");
		if(result.next()) fechaFin = result.getDate("fecha_hora_fin");
		result.getStatement().close();
		return fechaFin;
		}
	public String getFechaFinToString() throws SQLException
		{ return Util.format(getFechaFin(), "dd/MM/yyyy"); }

	public Date getFechaInicio() throws SQLException
		{
		Date fechaInicio = null;
		ResultSet result = MySQL.executeQuery("SELECT EtapasNewlong_Fechas('i', " + id + ") AS fecha_hora_fin");
		if(result.next()) fechaInicio = result.getDate("fecha_inicio");
		result.getStatement().close();
		return fechaInicio;
		}
	public String getFechaInicioToString() throws SQLException
		{ return Util.format(getFechaInicio(), "dd/MM/yyyy"); }

	public Formato getFormato() throws SQLException
		{
		if(formato == null || formatoId != formato.getId())
			{ formato = new Formato(formatoId); }
		return formato;
		}

	public int getFormatoId()
		{ return formatoId; }
	public void setFormatoId(int formatoId)
		{ this.formatoId = formatoId; }
	public void setFormatoId(String formatoId)
		{ try{ this.formatoId = Integer.parseInt(formatoId); }catch(Exception e) {}; }

	public CicloNewlong getCiclo() throws SQLException
		{
		if(ciclo == null || cicloId != ciclo.getId())
			{ ciclo = new CicloNewlong(cicloId); }
		return ciclo;
		}

	public int getCicloId()
		{ return cicloId; }
	public void setCicloId(int cicloId)
		{ this.cicloId = cicloId; }
	public void setCicloId(String cicloId)
		{ try{ this.cicloId = Integer.parseInt(cicloId); }catch(Exception e) {}; }

	@Override
	public String getDescriptor()
		{ return id+""; }

	@Override
	public String toJson()
		{
		HashMap map = new HashMap();
		map.put("id", id);
		map.put("formato_id", formatoId);
		map.put("ciclo_id", cicloId);
		map.put("orden", orden);
		map.put("cantidad", cantidad);
		map.put("ocupado", ocupado);
		try{
			map.put("fecha_inicio", Util.format(getFechaInicio(), "dd/MM/yyyy"));
			map.put("fecha_fin", Util.format(getFechaFin(), "dd/MM/yyyy"));
			}catch(Exception e) {}
		return new Gson().toJson(map);
		}



	// --- Metodos MySQL --- //

	@Override
	public String getNombreTabla()
		{ return NOMBRE_TABLA; }

	@Override
	public void leer(ResultSet result, String prefijo) throws SQLException
		{
		setId(result.getInt(prefijo + "id"));
		setOrden(result.getInt(prefijo + "orden"));
		setCantidad(result.getInt(prefijo + "cantidad"));
		setOcupado(result.getInt(prefijo + "ocupado"));
		setCicloId(result.getInt(prefijo + "ciclo_id"));
		setFormatoId(result.getInt(prefijo + "formato_id"));
		}

	@Override
	public void guardar() throws SQLException
		{
		ResultSet result = MySQL.executeQuery("Call EtapasNewlong_Assign(" +
				MySQL.formatId(id) + "," +
				MySQL.formatId(formatoId) + "," +
				MySQL.format(cicloId) + "," +
				MySQL.format(orden) + "," +
				MySQL.format(cantidad) + "," +
				MySQL.format(ocupado)  + ")");

		if(result.next())
			{
			if( result.getMetaData().getColumnCount() == 1)
				{
				String msj = result.getString("mensaje");
				throw new SQLException(msj);
				}
			else
				leer(result);
			}

		result.getStatement().close();
		}

	public static void borrar(String id) throws SQLException
		{ Entidad.borrar(id, NOMBRE_TABLA); }

	public static void cambiarOrden(int cicloId, String formato, int turno, boolean recalcular) throws SQLException
		{
		int formatoId = Formato.getId(formato);
		MySQL.executeUpdate("Call EtapasNewlong_CambiarOrden(" + cicloId + ", " + formatoId + ", " + turno + ", "+MySQL.formatBit(recalcular)+")");
		}
	
	public static List<EtapaNewlong> listar() throws SQLException
		{ return (List) Entidad.listar(EtapaNewlong.class, NOMBRE_TABLA, ""); }

	public static List<EtapaNewlong> listar(int cicloId) throws SQLException
		{ return (List) Entidad.buscar(EtapaNewlong.class, NOMBRE_TABLA, "ciclo_id = " + cicloId , "orden ASC"); }

	/**
	 * Devuelve un Map con las etapas de un ciclo, junto con las fechas de inicio y de fin de cada etapa.
	 *
	 * @param cicloId El identificador del ciclo.
	 * @return Devuelve un Map con los valores 'id', 'formatoId', 'cicloId', 'orden', 'cantidad', 'fechaInicio' y 'fechaFin'.
	 */
	public static List<HashMap> listarExt(int cicloId) throws SQLException
		{
		List<HashMap> res = new LinkedList();

		ResultSet result = MySQL.executeQuery("SELECT * FROM etapas_newlong_view WHERE ciclo_id = " + cicloId + " ORDER BY orden");
		while(result.next())
			{
			HashMap fila = new HashMap();
			fila.put("id", result.getInt("id"));
			fila.put("formatoId", result.getInt("formato_id"));
			fila.put("cicloId", result.getInt("ciclo_id"));
			fila.put("orden", result.getInt("orden"));
			fila.put("cantidad", result.getInt("cantidad"));
			fila.put("fechaInicio", Util.format(result.getTimestamp("fecha_inicio"), "dd/MM/yyyy HH:mm:ss"));
			fila.put("fechaFin", Util.format(result.getTimestamp("fecha_fin"), "dd/MM/yyyy HH:mm:ss"));
			res.add(fila);
			}
		result.getStatement().close();

		return res;
		}

	public static EtapaNewlong buscar(int cicloId, int formatoId) throws SQLException
		{
		List<EtapaNewlong> props = (List) Entidad.buscar(EtapaNewlong.class, NOMBRE_TABLA, "ciclo_id = " + cicloId + " AND formato_id = " + formatoId);
		if(props != null && props.size() > 0)
			{ return props.get(0); }
		else
			{ return null; }
		}

	/**
	 * Calcula la cantidad y las fechas de las etapas de un ciclo Newlong.
	 *
	 * Devuelve un objeto Map con el formato, el orden y la cantidad y las fechas de
	 * entrega y de fin de cada etapa (formatoId, orden, cantidad, fechaInicio, fechaFin).
	 *
	 * @param  newlongId El id de la maquina Newlong.
	 * @param  fechaInicio La fecha de inicio del ciclo.
	 * @param  fechaFin La fecha de fin del ciclo.
	 * @param  stringFormat Un booleano que indica si las fechas se guardaran como String o como Date.
	 * @return Devuelve un objeto Map con el formato, el orden y la cantidad y las fechas de entrega y de fin de cada etapa (formatoId, orden, cantidad, fechaInicio, fechaFin).
	 */
	public static List<Map> calcularFechasYCantidades(int newlongId, Date fechaInicio, Date fechaFin, List<FormatosPorNewlong> formatos, boolean stringFormat) throws SQLException
		{
		List<Map> proporciones = new LinkedList();

		long cantidad = Newlong.getCapacidad(newlongId, fechaInicio, fechaFin);
		float msXbolsa = (fechaFin.getTime() - fechaInicio.getTime())/cantidad;
		
		Date fecha1, fecha0 = fechaInicio;
		for(int i=0; i<formatos.size(); i++)
			{
			long cantidadFormato = formatos.get(i).getCantidad(cantidad);
			fecha1 = new Date(fecha0.getTime() + (long)msXbolsa*cantidadFormato);
			
			HashMap etapaExt = new HashMap();
			etapaExt.put("formatoId", formatos.get(i).getFormatoId());
			etapaExt.put("orden", formatos.get(i).getOrden());
			etapaExt.put("cantidad", cantidadFormato );
			if(stringFormat)
				{
				etapaExt.put("fechaInicio", Util.format(fecha0, "dd/MM/yyyy HH:mm:ss"));
				etapaExt.put("fechaFin", Util.format(fecha1, "dd/MM/yyyy HH:mm:ss"));
				}
			else
				{
				etapaExt.put("fechaInicio", fecha0);
				etapaExt.put("fechaFin", fecha1);
				}
			proporciones.add(etapaExt);

			fecha0 = fecha1;
			}

		return proporciones;
		}
	
	public static List<Map> calcularFechasYCantidades(int newlongId, Date fechaInicio, Date fechaFin, boolean stringFormat) throws SQLException
		{
		List<FormatosPorNewlong> formatos = FormatosPorNewlong.listar(newlongId);
		return calcularFechasYCantidades(newlongId, fechaInicio, fechaFin, formatos, true);
		}

	public static List<Map> calcularFechasYCantidades(int newlongId, Date fechaInicio, Date fechaFin) throws SQLException
		{ return calcularFechasYCantidades(newlongId, fechaInicio, fechaFin, true); }

        public static EtapaNewlong getEtapaByCicloYFormato(int cicloId, int formatoId) throws SQLException{
            LinkedList lista = new LinkedList();

            String query = "SELECT * FROM " + NOMBRE_TABLA + " where ciclo_id = " + cicloId + " and  formato_id = " + formatoId ;

             ResultSet result = null;
        try {
            result = MySQL.executeQuery(query);
            } catch (SQLException ex) {
            }

             while(result.next())
				{
                                EtapaNewlong entidad = null;
                                try {
                                    entidad = (EtapaNewlong) EtapaNewlong.class.newInstance();
                                    }catch (InstantiationException ex) {
                                    } catch (IllegalAccessException ex) {
                                   }
                                    entidad.leer(result);
                                   lista.add(entidad);
				}
                            result.getStatement().close();
            try {
                return (EtapaNewlong)lista.get(0);
            }catch (Exception e){
                return null;
            }
        }

        public void recalcular(int newlongId, Date fechaInicio, Date fechaFin,FormatosPorNewlong formato) throws SQLException{
             long cantidad = Newlong.getCapacidad(newlongId, fechaInicio, fechaFin);
	     float msXbolsa = (fechaFin.getTime() - fechaInicio.getTime())/cantidad;
             long cantidadFormato = formato.getCantidad(cantidad);
             this.setCantidad(cantidadFormato);
             this.setOrden(formato.getOrden());
//             this.setOcupado(0);
             this.guardar();

        }
}
